/*
 *  msw7/graphic2D.cpp
 *  mini
 *
 *  Created by jin on 1/1/11.
 *  Copyright 2011 cs. All rights reserved.
 *
 */

#include "msw7/graphic2d.h"

template<class Interface>
inline void
SafeRelease( Interface **ppInterfaceToRelease )
{
    if (*ppInterfaceToRelease != NULL)
    {
        (*ppInterfaceToRelease)->Release();

        (*ppInterfaceToRelease) = NULL;
    }
}

ID2D1Factory* MSW7Graphic2D::pD2DFactory = NULL;

bool MSW7Graphic2D::Init()
{
    return SUCCEEDED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory));
}

MSW7Graphic2D::MSW7Graphic2D()
    : m_pDCRT(NULL), m_pBlackBrush(NULL)
{
}

MSW7Graphic2D::~MSW7Graphic2D()
{
    DiscardDeviceResources();
}

void MSW7Graphic2D::BeginDraw()
{
    m_pDCRT->BeginDraw();
    m_pDCRT->SetTransform(D2D1::Matrix3x2F::Identity());
}

HRESULT MSW7Graphic2D::EndDraw()
{
    return m_pDCRT->EndDraw();
}

void MSW7Graphic2D::Resize(int width, int height)
{
    if (m_pDCRT)
    {
        D2D1_SIZE_U size;
        size.width = width;
        size.height = height;

        // Note: This method can fail, but it's okay to ignore the
        // error here -- it will be repeated on the next call to
        // EndDraw.
        m_pDCRT->Resize(size);
    }
}

HRESULT MSW7Graphic2D::CreateDeviceResources(HWND hwnd)
{
    HRESULT hr = S_OK;

    if (!m_pDCRT)
    {
        // Create a HWND render target.
        RECT rc;
        GetClientRect(hwnd, &rc);

        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
            );

        // Create a Direct2D render target.
        hr = pD2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hwnd, size),
            &m_pDCRT
            );

        if (SUCCEEDED(hr))
        {
            m_pDCRT->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black),
                &m_pBlackBrush
                );
        }
    }

    return hr;
}

void MSW7Graphic2D::DiscardDeviceResources()
{
    SafeRelease(&m_pBlackBrush);
    SafeRelease(&m_pDCRT);
}

void MSW7Graphic2D::clear_rect(float x, float y, float w, float h)
{
    // TODO: set clip, then clear
    m_pDCRT->Clear(D2D1::ColorF(D2D1::ColorF::White));
}

void MSW7Graphic2D::draw_line(float x0, float y0, float x1, float y1)
{
    m_pDCRT->DrawLine(
            D2D1::Point2F(x0, y0),
            D2D1::Point2F(x1, y1),
            m_pBlackBrush
            );
}
